Sprite Byte: Computer-Controlled Sprite

Level: Beginner - Intermediate

by Alyce Watson [http://alycesrestaurant.com/]


Home|Bitmap Help|Printing Forms|Tip Corner|Sprite Byte|Qcard Lesson 4|Do it Right!|Print with LB4.01|Long Filename Lister|Clearing Error Logs|Newsletter help|Index


Sprite Bytes are small tutorials that address a single method to be used with sprites in Liberty BASIC. See Sprite Bytes in previous newsletters for information on user-controls sprites, scrolling backgrounds and shooting. Please see the zipped archive of this newsletter for all files needed to run the demo program.

Sprites Controlled by the Computer

Most games have sprites that are controlled by the computer. These can be bad guys, missiles, obstacles, prizes, treasures, pickups, etc.

Creating an Enemy

An enemy ship!

For this demo, we'll add an enemy ship to the demos from previous Sprite Bytes. We must be concerned with the enemy's location, his speed, his direction of movement, and his boundaries.

Enemy Location

In our demo, the enemy ship will enter from the top of the screen and fly downwards toward the user-controlled ship. He starts with a Y coordinate of 0. The X coordinate can be determined in many ways. If there are several enemy ships, each might always fly at the same X location. It is more usual to have enemies appear in different locations. This can be determined randomly, with the RND() function.

        enemyX=int(rnd(0)*maxX)

We could easily start the enemy at the same X location as the ship, too. We do this by retrieving the coordinates of the ship and setting the enemy X equal to the current ship X.

        'start enemy at ship location:
        #1 "spritexy? ship sx sy"
        enemyX=sx

Enemy Speed

The enemy ship travels, so its Y coordinate must change with each frame. The larger the rate of change of the Y coordinate, the faster the enemy ship appears to move.

    enemyY=enemyY+5

For each frame, after we've specified new coordinates for the enemy, we use the spritexy command to redraw the enemy ship in its new location.

    #1 "spritexy enemy ";enemyX;" ";enemyY

Boundaries

When the enemy ship reaches the bottom of the screen, we reset its coordinates. It starts at the top, so we set its Y coordinate back to 0. We reset its X coordinate in one of the methods described above. The X boundaries are determined either by the location of the user-controlled ship, or by the algorithm in the RND() routine. The user-controlled ship has boundary checking in place, so there is an automatic boundary check when using this method. The RND method uses the maxX setting to determine the maximum X location for the enemy. The routine to move the enemy with each frame looks like this:

[moveEnemy]
    enemyY=enemyY+5
    'if enemy is at bottom, then move him
    'to top and reset X location randomly
    if enemyY>maxY then
        enemyY=0
        'start enemy in random location:
        enemyX=int(rnd(0)*maxX)
    end if
    #1 "spritexy enemy ";enemyX;" ";enemyY
    RETURN

Or, it looks like this, depending upon the method chosen to set the X coordinate.

[moveEnemy]
    enemyY=enemyY+5
    'if enemy is at bottom, then move him
    'to top and reset X location randomly
    if enemyY>maxY then
        enemyY=0
        'start enemy at ship location:
        #1 "spritexy? ship sx sy"
        enemyX=sx
    end if
    #1 "spritexy enemy ";enemyX;" ";enemyY
    RETURN

Direction of Travel

The routines above allow the enemy ship to proceed in a straight line down the screen. We can give the enemy some artificial intelligence quite easily. We do this by checking the X location of the ship with each frame and changing the enemy X coordinate to equal the ship X coordinate.

    'move enemy towards ship each frame:
    #1 "spritexy? ship sx sy"
    enemyX=sx

The entire routine to move the enemy ship then looks like this:

[moveEnemy]
    enemyY=enemyY+5

    'move enemy towards ship each frame:
    #1 "spritexy? ship sx sy"
    enemyX=sx

    'if enemy is at bottom, then move him
    'to top and reset X location randomly
    if enemyY>maxY then
        enemyY=0
        'start enemy at ship location:
        #1 "spritexy? ship sx sy"
        enemyX=sx
    end if
    #1 "spritexy enemy ";enemyX;" ";enemyY
    RETURN

Collisions!

We have a user-controlled ship, missiles fired by the ship, and an enemy ship. The only problem? Nothing happens when they collide! A future Sprite Byte will discuss collisions. Why wait, though? Why not play with the code and work out some collision handling routines of your own?


DEMO

Please find all of the support files for this program in the zipped archive for this issue.

'move sprite and shoot
'uses spritetravelxy
nomainwin
'ship is 40x40
'shot is 10x10
'enemy is 49x50
maxX=550 : maxY=400
WindowWidth=maxX+50 : WindowHeight=maxY+50

loadbmp "ship","ship.bmp"
loadbmp "shot","shoot.bmp"
loadbmp "enemy","enemy.bmp"

open "Adding an Enemy" for graphics_nsb_nf as #1
    #1 "trapclose [quit]"

    'create a black background with stars:
    #1 "down; fill black; color white"
    for i = 1 to 200
        x = int(rnd(0)*maxX)
        y = int(rnd(0)*maxY)
        #1 "set ";x;" ";y
    next
    #1 "getbmp bkg 0 0 ";maxX;" ";maxY

    'set the background
    #1 "background bkg"

    'add your sprites
    #1 "addsprite ship ship"
    #1 "addsprite enemy enemy"

    'add 10 identical missiles
    'all use same loaded bmp
    'concatenate sprite names
    for i = 1 to 10
        #1 "addsprite shot"+str$(i)+" shot"
    next

    'set ship location
    shipX=100 : shipY=maxY-20
    #1 "spritexy ship ";shipX;" ";shipY

    'set location of all missiles off screen
    shotX=-100 : shotY=-100
    for i = 1 to 10
        #1 "spritexy shot"+str$(i)+" ";shotX;" ";shotY
    next

    'set location for enemy
    enemyX=300 : enemyY=0
    #1 "spritexy enemy ";enemyX;" ";enemyY

    activeShot=0    'var to hold number of most recently fired missile

    bgX=0:bgY=0

    'show frame onscreen
    #1 "drawsprites"

    'set up to trap keypresses
    #1 "setfocus; when characterInput [check]"

[mainLoop]
    SCAN    'scan for user events
    gosub [moveship]
    gosub [moveEnemy]
    'slight pause to slow action:
    calldll #kernel32, "Sleep",10 as long, re as void
    goto [mainLoop]


[check]
    k$=Inkey$   'place value of Inkey$ into k$
    if k$="4" or asc(right$(k$,1))=37 then gosub [goLeft]
    if k$="6" or asc(right$(k$,1))=39 then gosub [goRight]
    if k$="8" or asc(right$(k$,1))=38 then gosub [goShoot]
    goto [mainLoop]

[goLeft]
    #1 "spritexy? ship x y"
    if x <= 0 then wait   'ship is at left side already
    shipX = shipX - 5
    return

[goRight]
    #1 "spritexy? ship x y"
    if x >= maxX then wait   'ship is at right side already
    shipX = shipX + 5
    return

[goShoot]
    activeShot=activeShot+1
    if activeShot>10 then activeShot=1
    #1 "spritexy? ship x y"
    'start shot near center of ship
    shotX=x+15:shotY=maxY
    'set shot to travel to top of screen and
    'fire event when it gets there
    #1 "spritexy shot"+str$(activeShot)+" ";shotX;" ";shotY
    #1 "spritetravelxy shot"+str$(activeShot)+" ";shotX;"  0 5 [checkShoot]"
    playwave "laser.wav", async
    return

[checkShoot]
    for i = 1 to 10
        #1 "spritexy? shot"+str$(i)+" sx sy"
        if sy<=0 then
            'move shot sprite off screen, update display
            #1 "spritexy shot"+str$(i)+" -100 -100"
        end if
    next
    #1 "drawsprites"    'update screen!
    goto [mainLoop]

[moveship]
    'put sprites in new location
    bgY=bgY-2   'scroll background
    #1 "backgroundxy ";bgX;" ";bgY
    #1 "spritexy ship ";shipX;" ";shipY
    #1 "drawsprites"    'update screen!
    RETURN

[moveEnemy]
    enemyY=enemyY+5

    'move enemy towards ship each frame:
    #1 "spritexy? ship sx sy"
    enemyX=sx

    'if enemy is at bottom, then move him
    'to top and reset X location randomly
    if enemyY>maxY then
        enemyY=0
        'start enemy in random location:
        'enemyX=int(rnd(0)*maxX)

        'start enemy at ship location:
        #1 "spritexy? ship sx sy"
        enemyX=sx
    end if
    #1 "spritexy enemy ";enemyX;" ";enemyY
    RETURN

[quit]
    unloadbmp "bkg"
    unloadbmp "ship"
    unloadbmp "shot"
    close #1:end


Home

Bitmap Help

Printing Forms

Tip Corner

Sprite Byte

Qcard Lesson 4

Do it Right!

Print with LB4.01

Long Filename Lister

Clearing Error Logs

Newsletter help

Index